#include "include/resource.h"
#include <QDebug>
Resource resource[20];
int cluster_ceiling_prio = PrioMin;

int get_resourcenum()
{
    int num=0;
    for(num=0;resource[num].resource_type!=0;num++)
    {}
    return num;
}

void resource_type_update()
{
    for(int j=0;j<get_tasknum();j++)
      {
          for(int k=0;k<RESOURCE_MAX;k++)
         {
          if((int)taskSets[j].resource_on_core[k]!=taskSets[j].on_core&&(int)taskSets[j].task_type!=-1&&taskSets[j].resource_duration[k]!=0)
          {
              resource[taskSets[j].resource_type[k]-1].is_global=true;
           }}
      }
}

bool SRT_task_try_to_get_local_resource(Task *task,Core *core,Resource *resource)
{
    task->temp_core=task->on_core;
    if(!resource->is_used)
  //if(task->task_priority<=cluster_ceiling_prio&&!resource->is_used)
     { cluster_ceiling_prio=resource->ceiling_prior;
       resource->is_used=true;
       resource->used_task_id=task->task_id;
       task->get_resource=true;
       return true;
     }
  else
  {
      resource_enqueue(task,resource);
      sched_DequeueLocal(task,core);
      sched_SetLocalSchedTask(nullptr,core);
      for(int i=0;i<get_tasknum();i++)
      {
        if(taskSets[i].task_id==resource->used_task_id)
            if(taskSets[i].task_priority>task->task_priority)
               taskSets[i].task_priority=task->task_priority;
      }
      return false;
  }

}

bool SRT_task_try_to_get_global_resource(Task *task,Core *newcore,Core *lastcore,Resource* resource)
{
    task->temp_core=newcore->core_id-1;
    //if(!resource->is_used||task->task_priority-PrioMin<newcore->ceiling_prior)
    if(!resource->is_used)
    {
        resource->used_task_id=task->task_id;
        resource->is_used=true;
        task->get_resource=true;
        task->task_priority-=100;
        newcore->ceiling_prior=resource->ceiling_prior;
        if(newcore->core_id!=lastcore->core_id)
        {
            sched_queueTrans(task,newcore->ready_queue,lastcore->ready_queue);
            sched_SetLocalSchedTask(nullptr,lastcore);
        }
     return true;
    }
    else
   {
    resource_enqueue(task,resource);
    sched_SetLocalSchedTask(nullptr,lastcore);
    return false;
    }

}

bool HRT_task_try_to_get_local_resource(Task *task,Core *core,Resource *resource)
{
    qDebug()<<"硬实时任务"<<task->task_id<<"基础优先级"<<task->task_priority<<"核"<<core->core_id<<"天花板优先级"<<core->ceiling_prior;
    task->temp_core=task->on_core;
    if(!resource->is_used)
    //if(task->task_priority<=core->ceiling_prior&&!resource->is_used)
    {
        resource->used_task_id=task->task_id;
        resource->is_used=true;
        task->get_resource=true;
        task->temp_core=core->core_id-1;
        qDebug()<<"资源优先级天花板为"<<resource->ceiling_prior;
        core->task_scheduled=task->task_id;
        core->ceiling_prior=resource->ceiling_prior;
        qDebug()<<"时间"<<Time<<"硬实时任务"<<task->task_id<<"获得局部资源"<<resource->resource_type;
        return true;
    }
    else
    {
        qDebug()<<"时间"<<Time<<"硬实时任务"<<task->task_id<<"进入资源"<<resource->resource_type<<"挂起队列";
        resource_enqueue(task,resource);
        show_suspendqueue(resource->resource_suspend_queue);
        sched_DequeueLocal(task,core);
        for(int i=0;i<i<get_tasknum();i++)
        if(taskSets[i].task_id==resource[task->resource_type[task->resource_index]-1].used_task_id)
        {
            taskSets[i].task_priority=task->task_priority;
            break;
        }
        sched_SetLocalSchedTask(nullptr,core);
        qDebug()<<"返回申请失败";
        return false;
    }
}

bool HRT_task_try_to_get_global_resource(Task *task,Core *newcore,Core *lastcore,Resource* resource)
{
    task->temp_core=newcore->core_id-1;
    if(!resource->is_used)
   //if(task->task_priority-PrioMin<newcore->ceiling_prior&&!resource->is_used)
   {
       resource->used_task_id=task->task_id;
       resource->is_used=true;
       task->get_resource=true;
       task->task_priority-=100;
       newcore->ceiling_prior=resource->ceiling_prior;
       if(newcore->core_id!=lastcore->core_id)
       {
           sched_queueTrans(task,newcore->ready_queue,lastcore->ready_queue);
           sched_SetLocalSchedTask(nullptr,lastcore);
       }
       return true;
   }
   else
  {
   resource_enqueue(task,resource);
   sched_SetLocalSchedTask(nullptr,lastcore);
   return false;
   }
}

void task_release_resource(Task *task,Resource *resource,Core *core)   //core代表迁回本地核
{
  if(resource->is_global)
  {
      qDebug()<<"时间"<<Time<<"任务"<<task->task_id<<"释放全局资源"<<resource->resource_type;
      task->get_resource=false;                      //boost prior置位
      resource->is_used=false;
      resource->used_task_id=-1;
      task->task_priority+=100;
      if(resource->resource_suspend_queue->next!=resource->resource_suspend_queue)
          for(int i=0;i<get_corenum();i++)
        {
         if(resource->resource_suspend_queue->next->task->temp_core==cores[i].core_id-1)
         {
         qDebug()<<"时间"<<Time<<"资源队列不为空，将资源挂起队列任务"<<resource->resource_suspend_queue->next->task->task_id<<"进入就绪队列";
         sched_queueTrans(resource->resource_suspend_queue->next->task,cores[i].ready_queue,resource->resource_suspend_queue);
         qDebug()<<"结束迁移";
         break;
         }
        }
          qDebug()<<"迁回本地核"<<task->on_core;    //迁回本核上
          sched_EnqueueLocal(task,core);
          sched_SetLocalSchedTask(nullptr,&cores[task->temp_core]);
          qDebug()<<"迁回本地核成功";
  }
  else
  {
    qDebug()<<"时间"<<Time<<"任务"<<task->task_id<<"释放局部资源";
    task->get_resource=false;
    resource->is_used=false;
    resource->used_task_id=-1;
    if(resource->resource_suspend_queue->next!=resource->resource_suspend_queue)
    {
        qDebug()<<"时间"<<Time<<"资源队列不为空，将资源挂起队列任务"<<resource->resource_suspend_queue->next->task->task_id<<"进入就绪队列";
      sched_queueTrans(resource->resource_suspend_queue->next->task,core->ready_queue,resource->resource_suspend_queue);
    }
    else
        qDebug()<<"就绪队列为空";
  }
}

void resource_enqueue(Task *task,Resource *resource)
{
    ready_queue_node *New = new ready_queue_node;
    New->task = task;
    ready_queue_node *pos;
    ready_queue_node *head = resource->resource_suspend_queue;
    for(pos = head->next; pos != head; pos = pos->next){
        if(pos->task->task_priority >= task->task_priority){
            add_task_list(New, pos->pre, pos);
            return;
        }
     }
    add_task_list_tail(New, head);
}

 void resource_denqueue(Task *task,Resource *resource)
  {
        ready_queue_node *pos;
        ready_queue_node *head = resource->resource_suspend_queue;
        for(pos = head->next; pos != head; pos = pos->next){
            if(pos->task == task){
                del_task_list(pos->pre, pos->next);
                delete pos;
                return;
            }
      }
  }


void resource_init(int resource_type)
{
    Resource *resource_temp = &resource[resource_type-1];

    resource_temp->is_global = false;
    resource_temp->resource_type = resource_type;
    resource_temp->is_used = false;
    resource_temp->used_task_id = -1;
    resource_temp->ceiling_prior = PrioMin;
    resource_temp->resource_suspend_queue = init_task_list_head();
}


void resource_bind(Task *task)
{
    for(int j=0;j<RESOURCE_MAX;j++)
        if(task->resource_duration[j]!=0)
    for(int i=0;i<get_resourcenum();i++)
        if(resource[i].resource_type==(int)task->resource_type[j])
         {   if(resource[i].is_bind==false)
            {
             resource[i].resource_on_core=task->on_core;
             task->resource_on_core[j]=resource[i].resource_on_core;
             resource[i].is_bind=true;
             qDebug()<<"资源"<<resource[i].resource_type<<"未绑定"<<"故绑定到核"<<task->on_core;
            }
            else
           {task->resource_on_core[j]=resource[i].resource_on_core;
           qDebug()<<"资源"<<resource[i].resource_type<<"已绑定到核"<<resource[i].resource_on_core;}
            break;
           }

}
